package com.shjy.driver.base;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.shjy.driver.R;
import com.printer.sdk.PrinterInstance;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Set;
import java.util.UUID;
/**
 * Created by zhouhuiming on 16/11/10.
 */

public class BluetoothPrint {

    public static String EXTRA_DEVICE_ADDRESS = "device_address";
    public static final int REQUESTCODE_BLUETOOTH_ENABLE = 1;
    public static final int REQUESTCODE_BLUETOOTH_OPENSETTING = 2;

    public static final int HANDLER_MSG_WHAT_READ = 100;
    public static final int HANDLER_MSG_WHAT_WRITE = 101;
    public static final int HANDLER_MSG_WHAT_DEVICE_NAME = 102;
    public static final int HANDLER_MSG_WHAT_CONN_FAIL = 404;
    public static final int HANDLER_MSG_WHAT_CONN_OFF = 405;

    private BluetoothAdapter bluetoothAdapter;
    private Activity activity;

    private BluetoothDevice btDevice;
    private BluetoothSocket btSocket;

    private AlertDialog dialog; //
    private Set<BluetoothDevice> paredDevice;
    private ArrayAdapter<String> paredDeviceAdapter;
    private TextView tv_no;
    private TextView tv_my_device;
    private ListView lv_connected_device;

    private ConnectThread mConnectThread;
    private ConnectPrintThread mPrintThread;

    public static final UUID MY_UUID = UUID
            .fromString("00001101-0000-1000-8000-00805F9B34FB");

    private Handler feeOverHandler;
    private static PrinterInstance mPrinter;

    public BluetoothPrint(Activity activity, Handler feeOverHandler){
        this.activity = activity;
        this.feeOverHandler = feeOverHandler;
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        paredDeviceAdapter = new ArrayAdapter<String>(activity, R.layout.item_bluetooth_list);

        if(!bluetoothAdapter.isEnabled()) {
            requestOpenBluetooth();
        } else {
            showConnectDevice();
        }
    }

    private String blueToothAddr;

    public BluetoothPrint(Activity activity, Handler feeOverHandler, String blueToothAddr){
        this.activity = activity;
        this.blueToothAddr = blueToothAddr;
        this.feeOverHandler = feeOverHandler;
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        paredDeviceAdapter = new ArrayAdapter<String>(activity, R.layout.item_bluetooth_list);
        bluetoothAdapter.startDiscovery();
        mPrinter = PrinterInstance.mPrinter;
        if(!bluetoothAdapter.isEnabled()) {
            requestOpenBluetooth();
        }
       /* else {
            String address = blueToothAddr.substring(blueToothAddr.length() - 17); //mac地址长度为17位，包括冒号
            connectBluetooth(address); //连接配对设备
        }*/
    }

    /**
     * 请求打开蓝牙
     */
    private void requestOpenBluetooth() {
        Intent it = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); //请求打开蓝牙
        it.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); //设置蓝牙可见性
        activity.startActivityForResult(it, REQUESTCODE_BLUETOOTH_ENABLE);
    }

    /**
     * 显示连接设备窗口
     */
    private void showConnectDevice() {
        bluetoothAdapter.startDiscovery();
        if(dialog == null) {
            AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity);
            dialogBuilder.setTitle("连接设备");
            View dialogView = activity.getLayoutInflater().inflate(R.layout.dialog_bluetooth_connect, null);
            dialogBuilder.setView(dialogView);

            tv_my_device = (TextView) dialogView.findViewById(R.id.tv_my_device);
            tv_my_device.setText(bluetoothAdapter.getName());

            TextView tv_search = (TextView) dialogView.findViewById(R.id.tv_search_device);
            tv_search.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    //打开蓝牙设置页面
                    Intent intent_conn = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
                    activity.startActivityForResult(intent_conn, REQUESTCODE_BLUETOOTH_OPENSETTING);
                }
            });
            tv_no = (TextView) dialogView.findViewById(R.id.tv_no);
			/*ListView */lv_connected_device = (ListView) dialogView.findViewById(R.id.lv_connected_device);
            lv_connected_device.setAdapter(paredDeviceAdapter);
            lv_connected_device.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                    // TODO Auto-generated method stub
                    String info = ((TextView) arg1).getText().toString();
                    String address = info.substring(info.length() - 17); //mac地址长度为17位，包括冒号

                    connectBluetooth(address); //连接配对设备
                    dialog.dismiss();
                }
            });

            this.dialog = dialogBuilder.create();
        }

        tv_my_device.setText(bluetoothAdapter.getName());

        updateParedDevices(); //更新已配对列表
        this.dialog.show();
    }

    /**
     * 更新已配对列表
     */
    private void updateParedDevices() {
        paredDevice = bluetoothAdapter.getBondedDevices();
        paredDeviceAdapter.clear();
        if(paredDevice.size() > 0) {

            if(tv_no != null) tv_no.setVisibility(View.GONE);

            for(BluetoothDevice btDevice : paredDevice) {
                paredDeviceAdapter.add(btDevice.getName() + "\n" + btDevice.getAddress());
            }
        } else {
            if(tv_no != null) tv_no.setVisibility(View.VISIBLE);
        }

        paredDeviceAdapter.notifyDataSetChanged();
    }

    /**
     * 连接配对设备
     * @param address 设备MAC地址值
     */
    private synchronized void connectBluetooth(String address) {
        btDevice = bluetoothAdapter.getRemoteDevice(address);

        if(mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }

        mConnectThread = new ConnectThread(btDevice);
        mConnectThread.start();
    }


    public synchronized void connectedSend(String printContent) {
        String address = blueToothAddr.substring(blueToothAddr.length() - 17);
        btDevice = bluetoothAdapter.getRemoteDevice(address);
        mPrintThread = new ConnectPrintThread(btDevice,printContent);
        mPrintThread.start();
        /*if(btSocket != null && btSocket.isConnected()) {
            *//*SPRTPrintThread sprtPrintThread = new SPRTPrintThread(btDevice,feeOverHandler,printContent);
            sprtPrintThread.start();*//*
            btDevice = bluetoothAdapter.getRemoteDevice(blueToothAddr);
            mPrintThread = new ConnectPrintThread(btDevice,printContent);
            mPrintThread.start();
        } else {
            showConnectDevice(); //显示连接窗口
        }*/

    }

    /**
     * This thread runs while attempting to make an outgoing connection with a
     * device. It runs str
     * aight through; the connection either succeeds or
     * fails.
     */
    private class ConnectThread extends Thread {
        //        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
        private String TAG = "BluetoothPrintActivity_ConnectThread";

        public ConnectThread(BluetoothDevice device) {
            mmDevice = device;

            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            /*try {
                btSocket = mmDevice.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (Exception e) {
                e.printStackTrace();
            }*/
        }

        public void run() {
            setName("ConnectThread");

            // Make a connection to the BluetoothSocket
            try {

                btSocket = mmDevice.createRfcommSocketToServiceRecord(MY_UUID);
                if(btSocket == null || !btSocket.isConnected()){
                    btSocket = mmDevice.createRfcommSocketToServiceRecord(MY_UUID);
                }

                // Always cancel discovery because it will slow down a connection
                bluetoothAdapter.cancelDiscovery();

                // This is a blocking call and will only return on a
                // successful connection or an exception
                btSocket.connect();
            } catch (Exception e) {
                e.printStackTrace();

                Message msg = feeOverHandler.obtainMessage(HANDLER_MSG_WHAT_CONN_FAIL,"蓝牙连接失败!");
                feeOverHandler.sendMessage(msg);
                // Start the service over to restart listening mode
//                BluetoothService.this.start();
                return;
            }

            /**
             * 显示连接状态，已连接设备名称
             */

            Message msg = feeOverHandler.obtainMessage(HANDLER_MSG_WHAT_DEVICE_NAME);
            Bundle bundle = new Bundle();
            bundle.putString(EXTRA_DEVICE_ADDRESS, mmDevice.getName());
            msg.setData(bundle);
            feeOverHandler.sendMessage(msg);
        }

        public void cancel() {
            try {
                btSocket.close();
//                mHandler.sendEmptyMessage(HANDLER_MSG_WHAT_CONN_OFF);
            } catch (IOException e) {
//                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }

    private class ConnectPrintThread extends Thread {
        private InputStream mmInStream;
        private OutputStream mmOutStream;
        private String TAG = "BluetoothActivity_ConnectedThread";
        private String charset = "GB2312"; //打印编码格式
        private String printContent;
        private BluetoothDevice mmDevice;

        public ConnectPrintThread(BluetoothDevice device, String printContent) {

            // Get the BluetoothSocket input and output streams
            try {
                mmDevice = device;
                mmInStream = new ByteArrayInputStream((printContent).getBytes(charset));
                this.printContent = printContent;
            } catch (IOException e) {
            }
        }

        private boolean connect(){
            boolean isConnect = true;
            try {
                bluetoothAdapter.cancelDiscovery();

                btSocket = mmDevice.createInsecureRfcommSocketToServiceRecord(MY_UUID);
//                btSocket = mmDevice.createRfcommSocketToServiceRecord(MY_UUID);
                if(btSocket == null){
                    btSocket = mmDevice.createRfcommSocketToServiceRecord(MY_UUID);
                }

                mmOutStream = btSocket.getOutputStream();

                // Always cancel discovery because it will slow down a connection

                // This is a blocking call and will only return on a
                // successful connection or an exception
                btSocket.connect();
            }catch (Exception e){

                if(btSocket != null){
                    btSocket.close();
                    btSocket = null;
                }
                e.printStackTrace();
                try {
                    isConnect = true;
                    btSocket =(BluetoothSocket) mmDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(mmDevice,1);
                    Thread.sleep(500);
                    btSocket.connect();
                }
                catch (Exception e2) {
                    isConnect = false;
                    e2.printStackTrace();
                }
            }finally {
                return isConnect;
            }
        }

        public void run() {
            if(!connect()){
                feeOverHandler.sendMessage(feeOverHandler.obtainMessage(HANDLER_MSG_WHAT_CONN_FAIL,"打印机连接失败!"));
                return;
            }
//            if (PrinterInstance.mPrinter != null){
//
//            }else {
//                feeOverHandler.sendMessage(feeOverHandler.obtainMessage(HANDLER_MSG_WHAT_CONN_FAIL,"打印机连接失败!"));
//                return;
//            }
//            mPrinter.sendBytesData(string2bytes("0x1B 0x33 0x00"));
//            mPrinter.sendBytesData(string2bytes("0x1B 0x4D 0x00"));
//            mPrinter.sendBytesData(string2bytes("0x1B 0x64 0x0C"));
//            mPrinter.sendBytesData(string2bytes("0x1B 0x4A 0x01"));
//            mPrinter.sendBytesData(string2bytes("0x1B 0x61 0x02"));

            write(string2bytes("0x1B 0x33 0x00"));
            write(string2bytes("0x1B 0x4D 0x00"));
            write(string2bytes("0x1B 0x64 0x0C"));
            write(string2bytes("0x1B 0x4A 0x01"));
            write(string2bytes("0x1B 0x61 0x02"));
            int length = -1;
            byte[] bytes = new byte[512];
            while(true) {
                try {
                    length = mmInStream.read(bytes);
                    if(length > 0) {
                        bytes = Arrays.copyOf(bytes, length);
                        //mPrinter.sendBytesData(bytes);
                        write(bytes);

//                        feeOverHandler.sendEmptyMessage(ParkingFeeOverFragment.HANDLER_MSG_WHAT_CONN_OFF);

                    } else {
                        //feeOverHandler.sendEmptyMessage(HANDLER_MSG_WHAT_CONN_OFF);
                        //mPrinter.sendBytesData(string2bytes("0x0C"));
                        write(string2bytes("0x0C"));
                        mmInStream.close(); //关闭输入流
                        mmOutStream.close();//关闭输出流
                        btSocket.close();
                        break;
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    try {
                        if(btSocket != null){
                            btSocket.close();
                        }
                        //feeOverHandler.sendEmptyMessage(HANDLER_MSG_WHAT_CONN_FAIL);
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    break;
                }
            }
        }

        public  byte[] string2bytes(String content){

            char[] charArray = content.toCharArray();
            byte[] tempByte = new byte[512];
            tempByte[0] = 0x34;
            try {
                int count = 0;
                for (int i = 0; i < charArray.length; i++) {

                    if (charArray[i] == 'x') {

                        tempByte[count++] = (byte) (char2Int(charArray[i + 1]) * 16 + char2Int(charArray[i + 2]));
                    }

                }
                byte[] retByte = new byte[count];
                System.arraycopy(tempByte, 0, retByte, 0, count);
            }catch (Exception ex){
                ex.printStackTrace();
            }
            return tempByte;
        }

        private int char2Int(char data){
            try {
                if (data >= 48 && data <= 57)//0~9
                    data -= 48;
                else if (data >= 65 && data <= 70)//A~F
                    data -= 55;
                else if (data >= 97 && data <= 102)//a~f
                    data -= 87;
            }catch (Exception ex){
                ex.printStackTrace();
            }
            return Integer.valueOf(data);
        }

        /**
         * Write to the connected OutStream.
         *
         * @param buffer The bytes to write
         */
        public void write(byte[] buffer) {

//            Log.i(TAG, "ConnectedThread write()");
            try {

//                Log.i(TAG, "ConnectedThread write() buffer=" + new String(buffer));

                mmOutStream.write(buffer);

            } catch (IOException e) {
//                Log.e(TAG, "Exception during write:---" + e.getMessage());
            }
        }
    }

    private class SPRTPrintThread extends Thread {
        private BluetoothDevice bluetoothDevice;
        private Handler handler;
        private PrinterInstance printerInstance;
        private String printContent;

        public SPRTPrintThread(BluetoothDevice bluetoothDevice, Handler handler, String printContent){
            this.bluetoothDevice = bluetoothDevice;
            this.handler = handler;
            this.printContent = printContent;
            printerInstance = PrinterInstance.getPrinterInstance(bluetoothDevice,handler);
        }

        @Override
        public void run() {
            if(printerInstance.openConnection()){
                printerInstance.printText(printContent);
            }
        }
    }

    /**
     * This thread runs during a connection with a remote device. It handles all
     * incoming and outgoing transmissions.
     */
    private class PrintThread extends Thread {
        private InputStream mmInStream;
        private OutputStream mmOutStream;
        private String TAG = "BluetoothActivity_ConnectedThread";
        private String charset = "GB2312"; //打印编码格式
        private String printContent;

        public PrintThread(BluetoothSocket socket, String printContent) {

            // Get the BluetoothSocket input and output streams
            try {
                mmOutStream = socket.getOutputStream();
                mmInStream = new ByteArrayInputStream((printContent).getBytes(charset));
                this.printContent = printContent;
            } catch (IOException e) {
            }
        }

        public void run() {


            int length = -1;
            byte[] bytes = new byte[512];
            while(true) {
                try {
                    length = mmInStream.read(bytes);
                    if(length > 0) {
                        bytes = Arrays.copyOf(bytes, length);
                        write(bytes);
//                        feeOverHandler.sendEmptyMessage(ParkingFeeOverFragment.HANDLER_MSG_WHAT_CONN_OFF);

                    } else {
                        feeOverHandler.sendEmptyMessage(HANDLER_MSG_WHAT_CONN_OFF);

                        mmInStream.close(); //关闭输入流
                        btSocket.close();
                        break;
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    try {
                        if(btSocket != null){
                            btSocket.close();
                        }
                        feeOverHandler.sendEmptyMessage(HANDLER_MSG_WHAT_CONN_FAIL);
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    break;
                }
            }
        }

        /**
         * Write to the connected OutStream.
         *
         * @param buffer The bytes to write
         */
        public void write(byte[] buffer) {

//            Log.i(TAG, "ConnectedThread write()");
            try {

//                Log.i(TAG, "ConnectedThread write() buffer=" + new String(buffer));

                mmOutStream.write(buffer);

            } catch (IOException e) {
//                Log.e(TAG, "Exception during write:---" + e.getMessage());
            }
        }
    }

    /**
     * 关闭连接
     */
    private void closeSocket() {
        try {
            if(btSocket != null && btSocket.isConnected()) {
                btSocket.close();
                btSocket = null;

//                mHandler.sendEmptyMessage(HANDLER_MSG_WHAT_CONN_OFF);
            } /*else {
    			toastMessage(R.string.text_no_conn);
    		}*/
        } catch (IOException e) {
//            Log.e(TAG, "close() of connect socket failed", e);
        }
    }


    private boolean isStop = false;
    public void observeConnState() { //监听蓝牙连接状态线程

        new Thread() {
            @Override
            public void run() {
                while(!isStop) {
                    if(btSocket == null || !btSocket.isConnected()) {
                        feeOverHandler.sendEmptyMessage(HANDLER_MSG_WHAT_CONN_OFF);
                    }

                    try {
                        sleep(200);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }










}
